package huanzhao.erp.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 用于文件操作的工具类
 *
 * @author April
 * 2024/1/5 17:54
 * @version 1.0
 */
@Slf4j
public class FileOpsUtil {
    public static final String THUMBNAIL = "thumbnail";
    public static final String PHOTOS = "photos";
    public static final String ATTACHES = "attaches";
    private static final String resources = AppContextUtil.getProperty("project.resources");
    public static final String auditFolder = join(resources, "audits");
    public static final String taskFolder = join(resources, "tasks");


    /**
     * 创建文件目录
     *
     * @return void
     * 2024/2/22 16:40:41
     */
    public static void init() {
        List<String> folders = List.of(auditFolder);
        for (String folderName : folders) {
            File folder = new File(folderName);
            if (!folder.exists()) {
                folder.mkdirs();
            }
        }
    }

    /**
     * 用于创建文件夹
     * 若文件夹已存在，则先执行删除操作
     *
     * @param folderName 文件夹名
     * @return boolean 返回是否操作失败
     * 2024/1/5 17:59:53
     */
    public static boolean createFolder(String folderName) {
        File folder = new File(folderName);
        if (folder.exists()) {
            delete(folderName);
        }
        return !folder.mkdirs();
    }


    /**
     * 根据工单id创建文件夹
     *
     * @param id 工单id
     *           2024/1/7 18:21:13
     */
    public static void createAuditFolder(Long id) {
        createFolder(join(auditFolder, String.valueOf(id), PHOTOS));
        createFolder(join(auditFolder, String.valueOf(id), ATTACHES));
    }

    public static String getSuffix(String filename) {
        if (filename == null) {
            return "";
        }
        int beginIndex = filename.lastIndexOf(".");
        return beginIndex == -1 ? "" : filename.substring(beginIndex);
    }

    /**
     * 连接多个路径
     *
     * @param paths 路径，可变参数
     * @return String
     * 2024/1/5 18:14:38
     */
    public static String join(String... paths) {
        return String.join(File.separator, paths);
    }

    /**
     * 将文件存放至指定路径
     *
     * @param file 接收到的文件
     * @param path 指定路径
     *             2024/1/5 18:20:05
     */
    public static void storageMPFile(MultipartFile file, String path) {
        try {
            file.transferTo(new File(path));
        } catch (IOException e) {
            log.error("文件保存失败，保存路径为：{}", path, e);
        }
    }

    /**
     * 移动源目录到目标目录
     *
     * @param source 源目录
     * @param target 目标目录
     * @return boolean 返回操作是否失败
     * 2024/1/6 13:17:05
     */
    private static boolean move(String source, String target) {
        File sourceFolder = new File(source);
        if (!sourceFolder.exists()) {
            return true;
        }
        File targetFolder = new File(target);
        if (targetFolder.exists()) {
            if (delete(target)) {
                return true;
            }
        }
        return !sourceFolder.renameTo(targetFolder);
    }

    /**
     * 递归删除路径下的所有文件
     *
     * @param path 路径
     * @return boolean 返回操作是否失败
     * 2024/1/5 21:49:45
     */
    public static boolean delete(String path) {
        File file = new File(path);
        if (!file.exists()) {
            return false;
        }
        //如果是目录，先递归删除其中所有文件和目录
        if (file.isDirectory()) {
            String[] files = file.list();
            if (files != null) {
                for (String filename : files) {
                    delete(join(path, filename));
                }
            }
        }
        return !file.delete();
    }

    /**
     * 获取工单的所有文件名
     *
     * @param auditId 工单id
     * @param type    文件类型
     * @return List<String>
     * 2024/1/7 12:44:59
     */
    public static List<String> getAuditFilenames(Long auditId, String type) {
        ArrayList<String> result = new ArrayList<>();
        File[] files = new File(join(auditFolder, String.valueOf(auditId), type)).listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isFile()) {
                    result.add(file.getName());
                }
            }
        }
        return result;
    }

    public static void uploadAuditFiles(Long id, MultipartFile[] photos, MultipartFile[] attaches) {
        createAuditFolder(id);
        if (photos != null && photos.length > 0) {
            uploadAuditPhotos(id, photos);
        }
        if (attaches != null && attaches.length > 0) {
            uploadAuditAttaches(id, attaches);
        }
    }

    public static void uploadTaskResultPhotos(Long taskId, MultipartFile[] photos) {
        String photoFolder = join(taskFolder, String.valueOf(taskId));
        createFolder(photoFolder);
        if (photos != null && photos.length > 0) {
            for (MultipartFile photo : photos) {
                String photoName = photo.getOriginalFilename();
                storageMPFile(photo, join(photoFolder, photoName));
            }
            generateThumbnails(photoFolder, join(photoFolder, THUMBNAIL));
        }
    }

    /**
     * 上传工单图片
     *
     * @param id     工单id
     * @param photos 图片列表
     *               2024/1/7 19:48:59
     */
    public static void uploadAuditPhotos(Long id, MultipartFile[] photos) {
        String photoFolder = join(auditFolder, String.valueOf(id), PHOTOS);
        for (MultipartFile photo : photos) {
            String photoName = photo.getOriginalFilename();
            storageMPFile(photo, join(photoFolder, photoName));
        }
        generateThumbnails(photoFolder, join(photoFolder, THUMBNAIL));
    }


    /**
     * 上传工单附件
     *
     * @param id       工单id
     * @param attaches 附件列表
     *                 2024/1/7 19:52:08
     */
    public static void uploadAuditAttaches(Long id, MultipartFile[] attaches) {
        String attachFolder = join(auditFolder, String.valueOf(id), ATTACHES);
        for (MultipartFile file : attaches) {
            String attachName = file.getOriginalFilename();
            storageMPFile(file, join(attachFolder, attachName));
        }
    }


    /**
     * 批量生成缩略图
     *
     * @param originFolder    原始图片文件夹路径
     * @param thumbnailFolder 缩略图保存文件夹路径
     */
    private static void generateThumbnails(String originFolder, String thumbnailFolder) {
        File originDir = new File(originFolder);
        createFolder(thumbnailFolder);
        File[] files = originDir.listFiles();
        if (files != null) {
            List<Thread> threads = new ArrayList<>();
            for (File file : files) {
                if (file.isFile()) {
                    String fileName = file.getName();
                    String srcImgPath = join(originFolder, fileName);
                    String outImgPath = join(thumbnailFolder, fileName);
                    // 生成缩略图
                    Thread thread = new Thread(() -> generateImageThumbnail(srcImgPath, outImgPath));
                    thread.start();
                    threads.add(thread);
                }
            }
            for (Thread thread : threads) {
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    log.error("批量生成缩略图失败，源文件夹：{}，缩略图文件夹：{}", originDir, thumbnailFolder, e);
                }
            }
        }
    }


    /**
     * 生成图片的缩略图
     *
     * @param srcImgPath 源文件路径
     * @param outImgPath 输出路径
     *                   2024/2/22 14:03:55
     */
    public static void generateImageThumbnail(String srcImgPath, String outImgPath) {
        try {
            // 读取原图片信息
            BufferedImage srcImg = ImageIO.read(new File(srcImgPath));
            // 图片宽、高
            int imgWidth = 600;
            // 缩放图片
            int imgHeight = srcImg.getHeight() * imgWidth / srcImg.getWidth();
            // 图片缓存
            BufferedImage bufferedThumbnail = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
            // 创建绘图工具
            Graphics2D graphics = bufferedThumbnail.createGraphics();
            // 使用更快速的缩放算法
            graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            // 直接在bufferedThumbnail上进行操作
            graphics.drawImage(srcImg.getScaledInstance(imgWidth, imgHeight, Image.SCALE_FAST), 0, 0, null);
            // 释放画图工具
            graphics.dispose();
            // 图片格式
            String format = srcImgPath.substring(srcImgPath.lastIndexOf(".") + 1);
            // 输出图片
            try (FileOutputStream fos = new FileOutputStream(outImgPath)) {
                ImageIO.write(bufferedThumbnail, format, fos);
            }
        } catch (IOException e) {
            log.error("生成缩略图失败, 源图片路径：{}，输出路径：{}", srcImgPath, outImgPath, e);
        }
    }
}
